var Biz_BoundDataGrid_RowDelimiter = ";"; 			    // Eg: "1,#CC00CC;2,#CC00CC"
var Biz_BoundDataGrid_RowAttributesDelimiter = ",";     // Eg: "<id>,<originalRowColor>"

// Global event variable. Used for FireFox because it doesn't have window.event property.
var Biz_BoundDataGrid_Window_Event;

function Biz_BoundDataGrid_RowClickedHandler(evt, row, sId, iRowSelectMode, sHiliteColor, sSelectedRowsTxtId, sLeftClickJScriptHandler, sRightClickJScriptHandler, sOnChangeJScriptHandler)
{
    Biz_BoundDataGrid_Window_Event = null;
    
    if (window.event != null)
        evt = window.event;       
        
	if (row == null  ||  sId == null)
		return;
		
	var singleRow = 0;
	var multiRow = 1;
	var multiRowWinStyle = 2;	

	var sParentGridId = row.parentNode.parentNode.id;
	var rowId = sParentGridId + "_Row_" + sId;
	var sSelectionBeforeClick = document.getElementById(sSelectedRowsTxtId).value;

	if (iRowSelectMode == singleRow)
	{
	    Biz_BoundDataGrid_DeselectAllRows(sParentGridId, sSelectedRowsTxtId);
	    var originalColor = Biz_BoundDataGrid_ColorToHex(row.style.backgroundColor);
	    Biz_BoundDataGrid_SelectRow(row, sId, originalColor, sHiliteColor, sSelectedRowsTxtId);
	}
	else if (iRowSelectMode == multiRow)
	{
	    var alreadyInList = Biz_BoundDataGrid_IsSelected(sId, sSelectedRowsTxtId);
		if (alreadyInList == false)
		{
			// Add row to the select list if it's not already in it.
		    var originalColor = Biz_BoundDataGrid_ColorToHex(row.style.backgroundColor);
		    Biz_BoundDataGrid_SelectRow(row, sId, originalColor, sHiliteColor, sSelectedRowsTxtId);
		}
		else
		{
			// Deselect row if it's already selected. Cannot deselect with right click.
			if (evt != null  &&  evt.button != 2)
			    Biz_BoundDataGrid_DeselectRow(row, sId, sSelectedRowsTxtId);
		}
	}
	else if (iRowSelectMode == multiRowWinStyle)
	{
		// Cannot select/deselect whit right click when in WinStyle mode.
		var isRightClick = (evt != null  &&  evt.button == 2);
		if (!isRightClick)
		{
			if (evt.ctrlKey)
			{
				// When CTRL is pressed the behavior is equal to MultiRow mode.
			    var alreadyInList = Biz_BoundDataGrid_IsSelected(sId, sSelectedRowsTxtId);
				if (alreadyInList == false)
				{
					// Add row to the select list if it's not already in it.
				    var originalColor = Biz_BoundDataGrid_ColorToHex(row.style.backgroundColor);
				    Biz_BoundDataGrid_SelectRow(row, sId, originalColor, sHiliteColor, sSelectedRowsTxtId);
				}
				else
				{
				    Biz_BoundDataGrid_DeselectRow(row, sId, sSelectedRowsTxtId);
				}
			}
			else
			{
				// If CTRL is not pressed the behavior is equal to SingleRow mode.
			    Biz_BoundDataGrid_DeselectAllRows(sParentGridId, sSelectedRowsTxtId);
			    var originalColor = Biz_BoundDataGrid_ColorToHex(row.style.backgroundColor);
			    Biz_BoundDataGrid_SelectRow(row, sId, originalColor, sHiliteColor, sSelectedRowsTxtId);
			}
		}
	}

	// Left click.
	if (evt != null  &&  evt.button < 2  &&  sLeftClickJScriptHandler != null  &&  sLeftClickJScriptHandler != "")
	{
		eval(sLeftClickJScriptHandler);
	}
	
	// Right click. Executes specified JavaScript function (usually a function that displays a context-menu).
	if (evt != null  &&  evt.button == 2  &&  sRightClickJScriptHandler != null  &&  sRightClickJScriptHandler != "")
	{
	    // Workaround for FireFox because it doesn't have window.event property.
	    var bReferencesEvent = sRightClickJScriptHandler.indexOf('event') >= 0;
	    if (bReferencesEvent && window.event == null)
	    {
	        Biz_BoundDataGrid_Window_Event = evt;
	        sRightClickJScriptHandler = sRightClickJScriptHandler.replace("event", "Biz_BoundDataGrid_Window_Event");
	    }

		eval(sRightClickJScriptHandler);
	}
	
	var sSelectionAfterClick = document.getElementById(sSelectedRowsTxtId).value;
	var bSelectionChanged = (sSelectionBeforeClick != sSelectionAfterClick);
	if (bSelectionChanged  &&  sOnChangeJScriptHandler != null  &&  sOnChangeJScriptHandler != "")
	    eval(sOnChangeJScriptHandler);
}

function Biz_BoundDataGrid_IsSelected(sId, sSelectedRowsTxtId)
{
	// Indicates whether the row with the given ID is selected.
	if (sId == null  ||  sSelectedRowsTxtId == null)
		return false;

	var txtSelectedRows = document.getElementById(sSelectedRowsTxtId);
	if (txtSelectedRows.value == "")
		return false;

	var arrRows = txtSelectedRows.value.split(Biz_BoundDataGrid_RowDelimiter);
	for (var i=0; i<arrRows.length; i++)
	{
		var sCurrRow = arrRows[i];
		var arrRowAttributes = sCurrRow.split(Biz_BoundDataGrid_RowAttributesDelimiter);
		var currId = arrRowAttributes[0];

		// If rows data ends with ';' then split method returns one crappy row whose ID is empty string.
		if (currId != null  &&  currId != "")
		{
			if (currId == sId)
				return true;
		}
	}

	return false;
}

function Biz_BoundDataGrid_SelectRow(row, sId, sOriginalColor, sHiliteColor, sSelectedRowsTxtId)
{
	if (row == null  ||  sId == null  ||  sOriginalColor == null  ||  sHiliteColor == null)
		return;

	// Selected rows data are in hidden text field.
	var txtSelectedRows = document.getElementById(sSelectedRowsTxtId);
	var rows = txtSelectedRows.value;
	rows += sId + Biz_BoundDataGrid_RowAttributesDelimiter + sOriginalColor + Biz_BoundDataGrid_RowDelimiter;
	txtSelectedRows.value = rows;

	// Hilite.
	Biz_BoundDataGrid_SetRowColor(row, sHiliteColor);
}

function Biz_BoundDataGrid_DeselectRow(row, sId, sSelectedRowsTxtId)
{
	// Creates a new select list without the specified row.
	// De-hilites row.

	if (row == null  ||  sId == null)
		return;

	var txtSelectedRows = document.getElementById(sSelectedRowsTxtId);
	if (txtSelectedRows.value == "")
		return;

	var arrRows = txtSelectedRows.value.split(Biz_BoundDataGrid_RowDelimiter);
	var sRemainingRows = "";

	for (var i=0; i<arrRows.length; i++)
	{
		var sCurrRow = arrRows[i];
		var arrRowAttributes = sCurrRow.split(Biz_BoundDataGrid_RowAttributesDelimiter);
		var currId = arrRowAttributes[0];
		var currOriginalColor = arrRowAttributes[1];

		// If rows data ends with ';' then split method returns one crappy row whose ID is empty string.
		if (currId != null  &&  currId != "")
		{
			if (currId != sId)
			    sRemainingRows += sCurrRow + Biz_BoundDataGrid_RowDelimiter;
			else
			    Biz_BoundDataGrid_SetRowColor(row, currOriginalColor);
		}
	}

	txtSelectedRows.value = sRemainingRows;
}

function Biz_BoundDataGrid_DeselectAllRows(sGridId, sSelectedRowsTxtId)
{
	var txtSelectedRows = document.getElementById(sSelectedRowsTxtId);
	if (txtSelectedRows.value == "")
		return;

	var arrRows = txtSelectedRows.value.split(Biz_BoundDataGrid_RowDelimiter);

	for (var i=0; i<arrRows.length; i++)
	{
		var sCurrRow = arrRows[i];
		var arrRowAttributes = sCurrRow.split(Biz_BoundDataGrid_RowAttributesDelimiter);
		var currId = arrRowAttributes[0];
		var currOriginalColor = arrRowAttributes[1];

		// If rows data ends with ';' then split method returns one crappy row whose ID is empty string.
		if (currId != null  &&  currId != "")
		{
			var rowId = sGridId + "_Row_" + currId;
			var row = document.getElementById(rowId);
			if (row != null)
			    Biz_BoundDataGrid_SetRowColor(row, currOriginalColor);
		}
	}

	txtSelectedRows.value = "";
}

function Biz_BoundDataGrid_SetRowColor(row, sColor)
{
	if (row != null  &&  sColor != null)
		row.style.backgroundColor = sColor;
}

function Biz_BoundDataGrid_GetSelectedValue(sSelectedRowsTxtId)
{
	var txtSelectedRows = document.getElementById(sSelectedRowsTxtId);
	if (txtSelectedRows.value == "")
		return null;
		
	// Returns the first selected value from the list.
	var arrRows = txtSelectedRows.value.split(Biz_BoundDataGrid_RowDelimiter);
	if (arrRows.length > 0)
	{
	    var arrRowAttributes = arrRows[0].split(Biz_BoundDataGrid_RowAttributesDelimiter);
		var sSelectedVal = arrRowAttributes[0];
		return sSelectedVal;
	}
	
	// No values are selected.
	return null;
}

function Biz_BoundDataGrid_ColorToHex(sColor)
{
    if (sColor == null || sColor == "")
        return sColor;

    var isRgb = ((sColor.length >= 3) && (sColor.substr(0, 3) == "rgb"));
    if (isRgb)
    {
        var hexFormat = sColor.replace(/rgb\(|\)/g, "").split(",");
        hexFormat[0] = parseInt(hexFormat[0], 10).toString(16).toLowerCase();
        hexFormat[1] = parseInt(hexFormat[1], 10).toString(16).toLowerCase();
        hexFormat[2] = parseInt(hexFormat[2], 10).toString(16).toLowerCase();
        hexFormat[0] = (hexFormat[0].length == 1) ? '0' + hexFormat[0] : hexFormat[0];
        hexFormat[1] = (hexFormat[1].length == 1) ? '0' + hexFormat[1] : hexFormat[1];
        hexFormat[2] = (hexFormat[2].length == 1) ? '0' + hexFormat[2] : hexFormat[2];
        return ('#' + hexFormat.join(""));
    }
    else
    {
        return sColor;
    }
}

// Grid "hotkeys" scripts.

function Biz_BoundDataGrid_PreviousItem(currCtl)
{
    var tr = Biz_BoundDataGrid_GetParentRow(currCtl);
    var prevTr = tr.previousSibling;    
    if (prevTr != null)
    {
        var isHeader = (prevTr.id == null) || (prevTr.id == "");
        if (!isHeader)
        {
            prevTr.click();
            if (prevTr.cells.length > 0)
                Biz_BoundDataGrid_TryFocus(prevTr.cells[0]);
        }
    }
}

function Biz_BoundDataGrid_NextItem(currCtl)
{
    var tr = Biz_BoundDataGrid_GetParentRow(currCtl);
    var nextTr = tr.nextSibling;
    if (nextTr != null)
    {
        var isFooter = (nextTr.id == null) || (nextTr.id == "");
        if (!isFooter)
        {
            nextTr.click();
            if (nextTr.cells.length > 0)
                Biz_BoundDataGrid_TryFocus(nextTr.cells[0]);
        }
    }
}

function Biz_BoundDataGrid_MoveUp(currCtl) 
{
    var td = Biz_BoundDataGrid_GetParentCell(currCtl);
    var idxCell = Biz_BoundDataGrid_GetCellIndex(td);
    var tr = Biz_BoundDataGrid_GetParentRow(currCtl);
    var prevTr = tr.previousSibling;
    if (prevTr != null)
    {        
        if (prevTr.cells.length > idxCell)
            Biz_BoundDataGrid_TryFocus(prevTr.cells[idxCell].firstChild);
    }
}

function Biz_BoundDataGrid_MoveDown(currCtl) 
{
    var td = Biz_BoundDataGrid_GetParentCell(currCtl);
    var idxCell = Biz_BoundDataGrid_GetCellIndex(td);
    var tr = Biz_BoundDataGrid_GetParentRow(currCtl);
    var nextTr = tr.nextSibling;
    if (nextTr != null)
    {
        if (nextTr.cells.length > idxCell)
            Biz_BoundDataGrid_TryFocus(nextTr.cells[idxCell].firstChild);
    }
}

function Biz_BoundDataGrid_MoveLeft(currCtl)
{
    var td = Biz_BoundDataGrid_GetParentCell(currCtl);
    var leftTd = td.previousSibling;
    if (leftTd != null) 
    {
        Biz_BoundDataGrid_TryFocus(leftTd.firstChild);
    }
}

function Biz_BoundDataGrid_MoveRight(currCtl)
{
    var td = Biz_BoundDataGrid_GetParentCell(currCtl);
    var rightTd = td.nextSibling;
    if (rightTd != null) 
    {
        Biz_BoundDataGrid_TryFocus(rightTd.firstChild);
    }
}

function Biz_BoundDataGrid_GetParentCell(ctl) 
{
    if (ctl == null)
        return null;
    else if (ctl.parentElement == null)
        return null;
    else if (ctl.parentElement.nodeName == "TD")
        return ctl.parentElement;
    else
        return Biz_BoundDataGrid_GetParentCell(ctl.parentElement);
}

function Biz_BoundDataGrid_TryFocus(ctl)
{
    if (ctl != null) 
    {
        try { ctl.focus(); }
        catch (e) { }
    }
}

function Biz_BoundDataGrid_GetCellIndex(td) 
{
    var row = td.parentElement;
    for (var idx = 0; idx < row.cells.length; idx++) 
    {
        var currCell = row.cells[idx];
        if (currCell == td)
            return idx;
    }

    return -1;
}

function Biz_BoundDataGrid_GetParentRow(ctl) 
{
    if (ctl == null)
        return null;
    else if (ctl.parentElement == null)
        return null;
    else if (ctl.parentElement.nodeName == "TR")
        return ctl.parentElement;
    else
        return Biz_BoundDataGrid_GetParentRow(ctl.parentElement);
}

function Biz_BoundDataGrid_ExecDefaultAction(currCtl)
{
    try { Biz_BoundDataGrid_GetParentRow(currCtl).ondblclick(); }
    catch (e) { }
}

function Biz_BoundDataGrid_OnHotKey(evt, previousItemKeyCode, nextItemKeyCode, defaultActionKeyCode, defaultAction, moveLeftKeyCode, moveUpKeyCode, moveRightKeyCode, moveDownKeyCode, deleteActionKeyCode, deleteAction)
{
    if (evt == null)
        evt = window.event;
    if (evt == null)
        return;
    var srcElement = (evt.srcElement) ? evt.srcElement : evt.target; 
    if (srcElement == null)
        return;

    if (previousItemKeyCode != null && evt.keyCode == previousItemKeyCode)
        Biz_BoundDataGrid_PreviousItem(srcElement);
    else if (nextItemKeyCode != null && evt.keyCode == nextItemKeyCode)
        Biz_BoundDataGrid_NextItem(srcElement);
    else if (defaultActionKeyCode != null && defaultAction != null && evt.keyCode == defaultActionKeyCode)
        Biz_BoundDataGrid_TryEval(defaultAction);
    else if (moveLeftKeyCode != null && evt.keyCode == moveLeftKeyCode)
        Biz_BoundDataGrid_MoveLeft(srcElement);
    else if (moveUpKeyCode != null && evt.keyCode == moveUpKeyCode)
        Biz_BoundDataGrid_MoveUp(srcElement);
    else if (moveRightKeyCode != null && evt.keyCode == moveRightKeyCode)
        Biz_BoundDataGrid_MoveRight(srcElement);
    else if (moveDownKeyCode != null && evt.keyCode == moveDownKeyCode)
        Biz_BoundDataGrid_MoveDown(srcElement);
    else if (deleteActionKeyCode != null && deleteAction != null && evt.keyCode == deleteActionKeyCode)
        Biz_BoundDataGrid_TryEval(deleteAction);
}

function Biz_BoundDataGrid_FocusRowWithDelay(sRowId, iDelayMs)
{
    var sCode = "Biz_BoundDataGrid_FocusRow('" + sRowId + "');";
    setTimeout(sCode, iDelayMs);
}

function Biz_BoundDataGrid_FocusRow(sRowId)
{
    var tr = document.getElementById(sRowId);
    if (tr != null)
    {
        tr.click();
        if (tr.cells.length > 0)
            Biz_BoundDataGrid_TryFocus(tr.cells[0]);
    }
}

function Biz_BoundDataGrid_TryEval(sCode)
{
    try { eval(sCode); }
    catch (e) { }
}